package com.xzk.ExpressInnWeb.dao.daoImp;

import com.xzk.ExpressInnWeb.bean.User;
import com.xzk.ExpressInnWeb.dao.BaseUserDao;
import com.xzk.ExpressInnWeb.util.DruidUtil;
import com.xzk.ExpressInnWeb.util.ParamType;
import com.xzk.ExpressInnWeb.util.QueryUtil;

import java.sql.*;
import java.util.*;
import java.util.Date;

public class UserDaoMySQL implements BaseUserDao {

    private static final String SQL_FIND_USER_BY_ID = "SELECT * FROM USER WHERE ID=?";
    private static final String SQL_CONSOLE_USER = "SELECT COUNT(ID) AS SIZE, COUNT(TO_DAYS(CREATETIME)=TO_DAYS(NOW()) OR NULL) AS DAY FROM USER";
    private static final String SQL_FIND_ALL_USERS = "SELECT * FROM USER";
    private static final String SQL_FIND_ALL_USERS_WITH_LIMIT = "SELECT * FROM USER LIMIT ? OFFSET ?";
    private static final String SQL_FIND_USER_BY_PHONE_NUMBER = "SELECT * FROM USER WHERE USERPHONE=?";
    private static final String SQL_INSERT_USER = "INSERT INTO USER (USERNAME,PERSONALID,USERPHONE,PASSWORD,CREATETIME) VALUES(?,?,?,?,NOW())";
    private static final String SQL_UPDATE_USER = "UPDATE USER SET USERNAME=?,PERSONALID=?,USERPHONE=?,PASSWORD=? WHERE ID=?";
    private static final String SQL_DELETE_USER = "DELETE FROM USER WHERE ID=?";
    private static final String SQL_UPDATE_LOGIN_TIME = "UPDATE USER SET LOGINTIME=? WHERE USERPHONE=?";
    private static final String SQL_LOGIN = "SELECT ID FROM USER WHERE USERPHONE=? AND PASSWORD=?";

    private Connection conn = null;
    private PreparedStatement state = null;
    private ResultSet rs = null;

    private String getType(Object o) {
        return o.getClass().toString();
    }

    private <T> User findUserBySingleValue(String sql, T param){
        User user = null;
        if (getType(param).endsWith("String")){
            rs = QueryUtil.query(
                    sql,
                    QueryUtil.getList(QueryUtil.getMap(ParamType.STRING,param)),
                    state, conn);
        } else if (getType(param).endsWith("Integer")) {
            rs = QueryUtil.query(
                    sql,
                    QueryUtil.getList(QueryUtil.getMap(ParamType.INT,param)),
                    state, conn);
        } else {
            System.err.println("无法处理的数据类型！");
        }
        if (rs != null){
            try {
                if (rs.next()){
                    user = buildUser(rs);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                DruidUtil.close(conn,state,rs);
            }
        }
        return user;
    }

    private User buildUser(ResultSet rs) {
        try {
            int id = rs.getInt("id");
            String username = rs.getString("username");
            String personalid = rs.getString("personalid");
            String userphone = rs.getString("userphone");
            String password = rs.getString("password");
            Timestamp createtime = rs.getTimestamp("createtime");
            Timestamp logintime = rs.getTimestamp("logintime");
            return new User(id,username,personalid,userphone,password,createtime,logintime);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return null;
    }

    @Override
    public User findUserByID(int id) {
        return findUserBySingleValue(SQL_FIND_USER_BY_ID, id);
    }

    @Override
    public Map<String, Integer> consoleUser() {
        Map<String, Integer> data = new HashMap<>();
        rs = QueryUtil.query(SQL_CONSOLE_USER, null, state, conn);
        try {
            if (rs.next()) {
                int size = rs.getInt("size");
                int day = rs.getInt("day");
                data.put("size",size);
                data.put("day",day);
            }
        } catch (SQLException|NullPointerException throwables) {
            throwables.printStackTrace();
        } finally {
            DruidUtil.close(conn,state,rs);
        }
        return data;
    }

    @Override
    public List<User> findAllUsers(boolean split, int offset, int limit) {
        ArrayList<User> data = new ArrayList<>();
        if (split) {
            rs = QueryUtil.query(
                    SQL_FIND_ALL_USERS_WITH_LIMIT,
                    QueryUtil.getList(QueryUtil.getMap(ParamType.INT, limit),
                            QueryUtil.getMap(ParamType.INT, offset)), state, conn);
        } else {
            rs = QueryUtil.query(SQL_FIND_ALL_USERS, null, state, conn);
        }
        try {
            while (rs.next()) {
                data.add(buildUser(rs));
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DruidUtil.close(conn,state,rs);
        }
        return data;
    }

    @Override
    public User findUserByPhoneNum(String userphone) {
        return findUserBySingleValue(SQL_FIND_USER_BY_PHONE_NUMBER, userphone);
    }

    @Override
    public boolean insertUser(User user) {
        String username = user.getUsername();
        String personalid = user.getPersonalid();
        String userphone = user.getUserphone();
        String password = user.getPassword();
        boolean result = false;
        try {
            result = QueryUtil.queryDML(
                    SQL_INSERT_USER,
                    QueryUtil.getList(
                            QueryUtil.getMap(ParamType.STRING,username),
                            QueryUtil.getMap(ParamType.STRING,personalid),
                            QueryUtil.getMap(ParamType.STRING,userphone),
                            QueryUtil.getMap(ParamType.STRING,password)),
                    state, conn);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean updateUser(int id, User newUser) {
        String username = newUser.getUsername();
        String personalid = newUser.getPersonalid();
        String userphone = newUser.getUserphone();
        String password = newUser.getPassword();
        boolean result = false;
        try {
            result = QueryUtil.queryDML(
                    SQL_UPDATE_USER,
                    QueryUtil.getList(
                            QueryUtil.getMap(ParamType.STRING,username),
                            QueryUtil.getMap(ParamType.STRING,personalid),
                            QueryUtil.getMap(ParamType.STRING,userphone),
                            QueryUtil.getMap(ParamType.STRING,password),
                            QueryUtil.getMap(ParamType.INT,id)),
                    state, conn);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return result;
    }

    @Override
    public boolean deleteUser(int id) {
        boolean result = false;
        try {
            result = QueryUtil.queryDML(
                    SQL_DELETE_USER,
                    QueryUtil.getList(QueryUtil.getMap(ParamType.INT, id)),
                    state, conn);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return result;
    }

    @Override
    public void updateLoginTime(String userphone, Date date) {
        try {
            QueryUtil.queryDML(
                    SQL_UPDATE_LOGIN_TIME,
                    QueryUtil.getList(
                            QueryUtil.getMap(ParamType.TIMESTAMP, new Timestamp(date.getTime())),
                            QueryUtil.getMap(ParamType.STRING,userphone)),
                    state, conn);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

    @Override
    public boolean login(String userphone, String password) {
        rs = QueryUtil.query(
                SQL_LOGIN,
                QueryUtil.getList(
                        QueryUtil.getMap(ParamType.STRING,userphone),
                        QueryUtil.getMap(ParamType.STRING,password)
                ),state, conn);
        try {
            return rs.next();
        } catch (SQLException|NullPointerException e) {
            e.printStackTrace();
        } finally {
            DruidUtil.close(conn, state, rs);
        }
        return false;
    }

}
